// Usage:
//
//	.\github_raw_download.exe -o root.go https://github.com/GetcharZp/light-proxy/blob/master/cmd/root.go
package main

import (
	"flag"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// 配置参数
var (
	outputFile string
	quietMode  bool
)

func init() {
	// 定义命令行标志
	flag.StringVar(&outputFile, "o", "", "输出文件路径")
	flag.BoolVar(&quietMode, "q", false, "静默模式，不显示下载进度")
}

// 解析GitHub URL并转换为Raw URL
func convertToRawURL(githubURL string) (string, error) {
	// 解析输入的URL
	u, err := url.Parse(githubURL)
	if err != nil {
		return "", fmt.Errorf("解析URL失败: %w", err)
	}

	// 检查是否是GitHub域名
	if u.Host != "github.com" {
		return "", fmt.Errorf("不支持的域名，仅支持github.com")
	}

	// 提取路径部分
	path := u.Path

	// 处理不同的GitHub URL格式
	// 示例:
	// - https://github.com/user/repo/blob/main/file.txt
	// - https://github.com/user/repo/tree/main/dir
	// - https://github.com/user/repo/raw/main/file.txt (直接使用raw路径)

	// 检查是否已经是raw路径
	if strings.Contains(path, "/raw/") {
		// 正确的raw路径格式应为: https://raw.githubusercontent.com/user/repo/branch/file
		// 但用户可能输入了错误的格式，如github.com/.../raw/...，需要进行转换
		if u.Host == "github.com" {
			// 移除多余的raw片段
			parts := strings.Split(path, "/")
			newParts := make([]string, 0, len(parts))
			for _, part := range parts {
				if part != "raw" {
					newParts = append(newParts, part)
				}
			}
			newPath := strings.Join(newParts, "/")
			return fmt.Sprintf("https://raw.githubusercontent.com%s", newPath), nil
		}
		return githubURL, nil
	}

	// 检查是否是blob路径(常见的文件查看页面)
	if strings.HasPrefix(path, "/") {
		parts := strings.Split(path, "/")
		// 典型的blob路径结构: /user/repo/blob/branch/path/to/file
		if len(parts) >= 5 && parts[3] == "blob" {
			// 正确的格式应为: https://raw.githubusercontent.com/user/repo/branch/path/to/file
			// 移除blob部分
			newParts := append(parts[:3], parts[4:]...)
			newPath := strings.Join(newParts, "/")
			return fmt.Sprintf("https://raw.githubusercontent.com%s", newPath), nil
		}

		// 检查是否是tree路径(目录查看页面)，不支持直接下载目录
		if len(parts) >= 5 && parts[3] == "tree" {
			return "", fmt.Errorf("不支持下载目录，请指定具体文件")
		}
	}

	return "", fmt.Errorf("无法识别的GitHub URL格式，请使用blob页面的URL")
}

// 下载文件
func downloadFile(rawURL, output string) error {
	// 创建HTTP客户端
	client := &http.Client{
		Timeout: 30 * time.Second,
	}

	// 发送GET请求
	if !quietMode {
		fmt.Printf("正在请求: %s\n", rawURL)
	}
	resp, err := client.Get(rawURL)
	if err != nil {
		return fmt.Errorf("请求失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("请求失败，状态码: %d", resp.StatusCode)
	}

	// 确定输出目标
	if output != "" {
		// 创建输出目录（如果不存在）
		outputDir := filepath.Dir(output)
		if outputDir != "." {
			if err := os.MkdirAll(outputDir, 0755); err != nil {
				return fmt.Errorf("创建目录失败: %w", err)
			}
		}

		// 创建文件
		file, err := os.Create(output)
		if err != nil {
			return fmt.Errorf("创建文件失败: %w", err)
		}
		defer file.Close()

		if !quietMode {
			fmt.Printf("开始下载到文件: %s\n", output)
		}

		// 复制响应体到文件
		_, err = io.Copy(file, resp.Body)
		if err != nil {
			return fmt.Errorf("写入文件失败: %w", err)
		}

		if !quietMode {
			fmt.Printf("下载完成，保存至: %s\n", output)
		}
	} else {
		// 输出到标准输出
		if !quietMode {
			fmt.Println("下载内容到标准输出:")
		}
		_, err = io.Copy(os.Stdout, resp.Body)
		if err != nil {
			return fmt.Errorf("写入标准输出失败: %w", err)
		}
	}

	return nil
}

func main() {
	// 解析命令行参数
	flag.Parse()

	// 检查是否提供了GitHub URL
	if flag.NArg() < 1 {
		fmt.Println("用法: github-raw-download [选项] <GitHub URL>")
		fmt.Println("选项:")
		flag.PrintDefaults()
		os.Exit(1)
	}

	githubURL := flag.Arg(0)

	// 转换为Raw URL
	rawURL, err := convertToRawURL(githubURL)
	if err != nil {
		fmt.Fprintf(os.Stderr, "错误: %v\n", err)
		os.Exit(1)
	}

	if !quietMode {
		fmt.Printf("转换后的Raw URL: %s\n", rawURL)
	}

	// 下载文件
	if err := downloadFile(rawURL, outputFile); err != nil {
		fmt.Fprintf(os.Stderr, "下载失败: %v\n", err)
		os.Exit(1)
	}
}
